home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
198_02
/
search.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-21
|
42KB
|
1,780 lines
/*
* The functions in this file implement commands that search in the forward
* and backward directions. There are no special characters in the search
* strings. Probably should have a regular expression search, or something
* like that.
*
* Aug. 1986 John M. Gamble:
* Made forward and reverse search use the same scan routine.
*
* Added a limited number of regular expressions - 'any',
* 'character class', 'closure', 'beginning of line', and
* 'end of line'.
*
* Replacement metacharacters will have to wait for a re-write of
* the replaces function, and a new variation of ldelete().
*
* For those curious as to my references, i made use of
* Kernighan & Plauger's "Software Tools."
* I deliberately did not look at any published grep or editor
* source (aside from this one) for inspiration. I did make use of
* Allen Hollub's bitmap routines as published in Doctor Dobb's Journal,
* June, 1985 and modified them for the limited needs of character class
* matching. Any inefficiences, bugs, stupid coding examples, etc.,
* are therefore my own responsibility.
*
* April 1987: John M. Gamble
* Deleted the "if (n == 0) n = 1;" statements in front of the
* search/hunt routines. Since we now use a do loop, these
* checks are unnecessary. Consolidated common code into the
* function delins(). Renamed global mclen matchlen,
* and added the globals matchline, matchoff, patmatch, and
* mlenold.
* This gave us the ability to unreplace regular expression searches,
* and to put the matched string into an evironment variable.
* SOON TO COME: Meta-replacement characters!
*
* 25-apr-87 DML
* - cleaned up an unneccessary if/else in forwsearch() and
* backsearch()
* - savematch() failed to malloc room for the terminating byte
* of the match string (stomp...stomp...). It does now. Also
* it now returns gracefully if malloc fails
*
* July 1987: John M. Gamble
* Set the variables matchlen and matchoff in the 'unreplace'
* section of replaces(). It would confuse the function
* savematch() if you replaced, unreplaced, then replaced
* again (serves you right for being so wishy-washy...)
*/
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
#if LATTICE | C86 | DECUSC
#define void int
#endif
#if C86
#define STATIC /* */
#else
#if DECUSC
#define STATIC extern
#else
#define STATIC static
#endif
#endif
/* UCAST must map a possibly signed char to an unsigned value */
/* In standard C, (unsigned int) will sign extend first like (int) */
/* Not all compilers understand (unsigned char) */
#if LATTICE | C86 | DECUSC | BSD29 | V7 | CPM | WMCS
#define UCAST (unsigned int)
#else
#define UCAST (unsigned char)
#endif
STATIC int amatch();
STATIC int readpattern();
STATIC int replaces();
STATIC int nextch();
STATIC int mcstr();
STATIC int mceq();
STATIC int cclmake();
STATIC int biteq();
#if MAGIC
STATIC void setbit();
STATIC BITMAP clearbits();
#endif
#if DECUSC
#define STATIC /* */
#endif
static int deltaf[HICHAR], deltab[HICHAR];
static int lastchfjump, lastchbjump;
static int patlenadd;
/*
* forwsearch -- Search forward. Get a search string from the user, and
* search for the string. If found, reset the "." to be just after
* the match string, and (perhaps) repaint the display.
*/
forwsearch(f, n)
int f, n; /* default flag / numeric argument */
{
register int status;
status = TRUE;
/* If n is negative, search backwards.
* Otherwise proceed by asking for the search string.
*/
if (n < 0)
return(backsearch(f, -n));
/* Ask the user for the text of a pattern. If the
* response is TRUE (responses other than FALSE are
* possible), search for the pattern for as long as
* n is positive (n == 0 will go through once, which
* is just fine).
*/
if ((status = readpattern("Search", &pat[0], TRUE)) == TRUE) {
do {
#if MAGIC
if (magical && (curwp->w_bufp->b_mode & MDMAGIC) != 0)
status = mcscanner(&mcpat[0], FORWARD, PTEND);
else
#endif
status = scanner(&pat[0], FORWARD, PTEND);
} while ((--n > 0) && status);
/* Save away the match, or complain
* if not there.
*/
if (status != TRUE)
mlwrite("Not found");
}
return(status);
}
/*
* forwhunt -- Search forward for a previously acquired search string.
* If found, reset the "." to be just after the match string,
* and (perhaps) repaint the display.
*/
forwhunt(f, n)
int f, n; /* default flag / numeric argument */
{
register int status;
status = TRUE;
if (n < 0) /* search backwards */
return(backhunt(f, -n));
/* Make sure a pattern exists, or that we didn't switch
* into MAGIC mode until after we entered the pattern.
*/
if (pat[0] == '\0')
{
mlwrite("No pattern set");
return (FALSE);
}
#if MAGIC
if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 &&
mcpat[0].mc_type == MCNIL)
{
if (!mcstr())
return (FALSE);
}
#endif
/* Search for the pattern for as long as
* n is positive (n == 0 will go through once, which
* is just fine).
*/
do
{
#if MAGIC
if (magical && (curwp->w_bufp->b_mode & MDMAGIC) != 0)
status = mcscanner(&mcpat[0], FORWARD, PTEND);
else
#endif
status = scanner(&pat[0], FORWARD, PTEND);
} while ((--n > 0) && status);
/* Save away the match, or complain
* if not there.
*/
if (status != TRUE)
mlwrite("Not found");
return(status);
}
/*
* backsearch -- Reverse search. Get a search string from the user, and
* search, starting at "." and proceeding toward the front of the buffer.
* If found "." is left pointing at the first character of the pattern
* (the last character that was matched).
*/
backsearch(f, n)
int f, n; /* default flag / numeric argument */
{
register int status;
status = TRUE;
/* If n is negative, search forwards.
* Otherwise proceed by asking for the search string.
*/
if (n < 0)
return(forwsearch(f, -n));
/* Ask the user for the text of a pattern. If the
* response is TRUE (responses other than FALSE are
* possible), search for the pattern for as long as
* n is positive (n == 0 will go through once, which
* is just fine).
*/
if ((status = readpattern("Reverse search", &pat[0], TRUE)) == TRUE) {
do {
#if MAGIC
if (magical && (curwp->w_bufp->b_mode & MDMAGIC) != 0)
status = mcscanner(&tapcm[0], REVERSE, PTBEG);
else
#endif
status = scanner(&tap[0], REVERSE, PTBEG);
} while ((--n > 0) && status);
/* Save away the match, or complain
* if not there.
*/
if (status != TRUE)
mlwrite("Not found");
}
return(status);
}
/*
* backhunt -- Reverse search for a previously acquired search string,
* starting at "." and proceeding toward the front of the buffer.
* If found "." is left pointing at the first character of the pattern
* (the last character that was matched).
*/
backhunt(f, n)
int f, n; /* default flag / numeric argument */
{
register int status;
status = TRUE;
if (n < 0)
return(forwhunt(f, -n));
/* Make sure a pattern exists, or that we didn't switch
* into MAGIC mode until after we entered the pattern.
*/
if (tap[0] == '\0')
{
mlwrite("No pattern set");
return (FALSE);
}
#if MAGIC
if ((curwp->w_bufp->b_mode & MDMAGIC) != 0 &&
tapcm[0].mc_type == MCNIL)
{
if (!mcstr())
return (FALSE);
}
#endif
/* Go search for it for as long as
* n is positive (n == 0 will go through once, which
* is just fine).
*/
do
{
#if MAGIC
if (magical && (curwp->w_bufp->b_mode & MDMAGIC) != 0)
status = mcscanner(&tapcm[0], REVERSE, PTBEG);
else
#endif
status = scanner(&tap[0], REVERSE, PTBEG);
} while ((--n > 0) && status);
/* Save away the match, or complain
* if not there.
*/
if (status != TRUE)
mlwrite("Not found");
return(status);
}
#if MAGIC
/*
* mcscanner -- Search for a meta-pattern in either direction. If found,
* reset the "." to be at the start or just after the match string